#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>

// peripharal files:
#include "rand.h"

int seed [N_RAND];
char in_buff [BUFSIZE];
char out_buff [BUFSIZE];
char rand_buff [BUFSIZE];

char in_name [256];
char out_name [256];

// Get the file size and place file pointer to beginning of file
int get_file_size (FILE * f)
{
	int s;
	fseek (f, 0, SEEK_END);
	s = ftell (f);
	fseek (f, 0, SEEK_SET);
	return s;
}

// Generate a buffer of random bytes that is the length of the write buffer
int make_random_buffer (char * local_rand_buff)
{	
	static char * ran;
	unsigned int accum = 0;
	unsigned int next_batch = 0;
	while (accum < BUFSIZE)
	{	
		if (accum + RAND_SIZE < BUFSIZE)
			next_batch = RAND_SIZE;
		else
			next_batch = BUFSIZE - accum;

		ran = (char *) i_rand ();
		memcpy (local_rand_buff + accum, ran, next_batch); 
		accum += next_batch;
	}
	return 0;
}

int apply_xor (FILE * in, FILE * out)
{
	static unsigned int accum, f_size, next_batch, i;
	accum = f_size = next_batch = 0;

	// Get input file size, of course it's the same as the output
	f_size = get_file_size (in);

	// go back to beginning of file, for both.
	fseek (in, 0, SEEK_SET); fseek (out, 0, SEEK_SET);
	while (accum < f_size)
	{
		if (accum + BUFSIZE < f_size)
			next_batch = BUFSIZE;
		else
			next_batch = f_size - accum;

		// Get next set or random bytes
		make_random_buffer (rand_buff);

		fread (in_buff, sizeof (char), next_batch, in);

		for (i=0; i<next_batch; i++)
			out_buff [i] = in_buff [i] ^ rand_buff [i];
		
		fwrite (out_buff, sizeof (char), next_batch, out);
		
		accum += next_batch;
	}
	return 0;
}

int main (int argc, char * argv [])
{
	FILE * enc, * dec;
	unsigned int i;

	for (i=0; i<N_RAND; i++)
		seed [i] = 1;
	i_seed (seed);

	sprintf (in_name,"%s",argv[1]);
	sprintf (out_name,"%s",argv[2]);

	if ( !strcmp (in_name, out_name) )
	{
		printf("Input and output are same file. Can't do this.\n");
		exit (1);
	}
	
	enc = fopen (in_name,"rb");
	dec = fopen (out_name,"wb");

	apply_xor (enc, dec);

	fclose (enc); fclose (dec);

	return 0;
}
